package com.huawang.mdesign.model.service.inter;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.google.gson.Gson;
import com.huawang.business.command.CommandAddType;
import com.huawang.business.command.CommandParameter;
import com.huawang.business.constants.ErrorCode;
import com.huawang.business.constants.ModelConstantURI;
import com.huawang.business.constants.SystemConstants;
import com.huawang.business.dto.*;
import com.huawang.business.dto.project.Project;
import com.huawang.business.dto.property.ItemInfo;
import com.huawang.business.exception.AbortExecutionException;
import com.huawang.business.service.judge.BusinessJudgeService;
import com.huawang.business.service.model.base.ModelManagerConfig;
import com.huawang.business.service.model.base.UmlService;
import com.huawang.business.service.model.core.*;
import com.huawang.business.service.model.core.project.ProjectManager;
import com.huawang.business.service.model.core.property.PropertyManager;
import com.huawang.business.service.model.core.property.UpdateModelFactory;
import com.huawang.business.service.model.core.property.update.IUpdateProperty;
import com.huawang.business.service.model.core.property.update.UpdatePropertyFactory;
import com.huawang.business.service.model.parse.excel.ExcelData;
import com.huawang.business.service.model.parse.excel.ExcelParser;
import com.huawang.business.service.model.parse.excel.SheetData;
import com.huawang.business.service.transaction.TransactionServiceImpl;
import com.huawang.business.util.InstanceVoUtils;
import com.huawang.business.vo.ModelResultVo;
import com.huawang.business.vo.RelationshipVo;
import com.huawang.core.definition.mof.UMLDefinitionConstants;
import com.huawang.core.definition.mof.cmof.reflection.impl.BasicRElement;
import com.huawang.core.definition.mof.instances.MetaClassInstance;
import com.huawang.core.semantics.constants.RelationConstraints;
import com.huawang.core.semantics.constants.TypeEnum;
import com.huawang.core.semantics.entity.transaction.LocalTransaction;
import com.huawang.core.semantics.exception.LocalTransactionNotStartException;
import com.huawang.core.semantics.exception.TransactionNotExistingException;
import com.huawang.mdesign.model.service.dto.*;
import com.huawang.mdesign.model.service.facade.importer.ImportDataService;
import com.huawang.mdesign.model.service.util.ImportAndExportUtils;
import com.huawang.mdesign.model.service.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.huawang.business.constants.ModelActionName.*;

@Service
@Slf4j
public class ImportService {
    @Autowired
    private ProjectManager projectManager;

    @Autowired
    private UmlService umlService;

    @Autowired
    private InternalUmlService internalUmlService;

    @Autowired
    private ModelPropertyInfoService modelPropertyInfoService;

    @Autowired
    private DiagramTableService diagramTableService;

    @Autowired
    private ModelService modelService;

    @Autowired
    private RelationshipService relationshipService;

    @Autowired
    private TransactionServiceImpl transactionService;

    @Autowired
    private UpdatePropertyFactory updatePropertyFactory;

    @Autowired
    private PropertyManager propertyManager;

    @Autowired
    private ImportDataService importDataService;

    @Autowired
    private InternalPropertyService internalPropertyService;

    @Autowired
    private ModelManagerConfig modelManagerConfig;

    public static final String EXPORT_LF = ",";

    private static final String UPDATE_PREFIX = "update";

    private static final String REMOVE_FROM_DIAGRAM = "2";

    private static final String DELETE_MODEL = "3";

    /**
     * desciption:读取Excel/CSV文件
     *
     * @param fileUrl
     * @return java.util.List<com.huawang.mdesign.model.service.parse.excel.SheetData>
     * @author lx
     * @date 2023/9/25
     */
    public List<SheetData> importPreview(String fileUrl) {
        log.info("导入的文件路径为：" + fileUrl);
        List<SheetData> sheetDataVoList = new ArrayList<>();
        BufferedReader br = null;
        try {
            if (fileUrl.contains("csv")) {
                SheetData sheetData = new SheetData();
                String encode = ImportAndExportUtils.getCsvEncoding(fileUrl);
                br = Files.newBufferedReader(Paths.get(fileUrl), Charset.forName(encode));
                String line;
                while ((line = br.readLine()) != null) {
                    String[] columns = line.split(",");
                    List<String> list = Arrays.asList(columns);
                    sheetData.getValues().add(list.stream().map(it -> it.replace("\"", "")).collect(Collectors.toList()));
                }
                sheetDataVoList.add(sheetData);
            } else {
                final ExcelParser excelParser = new ExcelParser();
                final ExcelData excelData = excelParser.parse(fileUrl);
                if (Objects.isNull(excelData)) {
                    log.info("表格数据为空");
                    return Collections.emptyList();
                }
                sheetDataVoList = excelData.getSheets();
            }
        } catch (IOException e) {
            log.error("文件读取失败", e);
            throw AbortExecutionException.build(ErrorCode.READ_FILE_ERROR, e);
        } finally {
            if (Objects.nonNull(br)) {
                try {
                    br.close();
                } catch (IOException e) {
                    log.error("文件流关闭异常", e);
                }
            }

        }
        if (CollectionUtils.isEmpty(sheetDataVoList)) {
            log.info("表格数据为空");
            return Collections.emptyList();
        }
        return sheetDataVoList;
    }


    public ImportInfoVo importModelElementOnGlobal(ImportConfigDTO importConfigDTO) {
        return importModelElement(importConfigDTO);
    }


    public ImportInfoVo diagramImportModelElementOnConfig(DiagramImportElementDTO diagramImportElementDTO) {
        final String projectId = diagramImportElementDTO.getProjectId();
        MetaClassInstance instance = internalUmlService.fetchInstance(diagramImportElementDTO.getInstanceId(), projectId);
        if (Objects.isNull(instance)) {
            log.error("导入配置模型查找失败:{}", diagramImportElementDTO.getInstanceId());
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        DiagramImportConfigDTO diagramImportConfigDTO = new DiagramImportConfigDTO();
        diagramImportConfigDTO.setProjectId(projectId);
        ModelPropertyInfo importConfigModel = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId,
                instance,
                Stream.of(UMLDefinitionConstants.Design_Profile_MapToDataSource_url,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_sheet,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_firstCell,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_identificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_sourceIdentificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_targetIdentificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_mappingColumns,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_firstRowRepresentsHeading,
                        UMLDefinitionConstants.Design_Profile_DiagramTableMapToDataSource_deleteRowOption).collect(Collectors.toList()));
        setMapToDataSourceProperty(diagramImportConfigDTO, importConfigModel);
        diagramImportConfigDTO.setDeleteRowOption(importConfigModel.queryStringValue(UMLDefinitionConstants.Design_Profile_DiagramTableMapToDataSource_deleteRowOption));
        diagramImportConfigDTO.setInstanceId(diagramImportElementDTO.getInstanceId());
        diagramImportConfigDTO.setMetaclassOrStereotype(diagramImportElementDTO.getMetaclassOrStereotype());
        diagramImportConfigDTO.setAttachfileDir(diagramImportElementDTO.getAttachfileDir());
        diagramImportConfigDTO.setOwnerId(diagramImportElementDTO.getOwnerId());
        return diagramImportModelElement(diagramImportConfigDTO);
    }

    public ImportInfoVo importModelElementOnConfig(ImportElementDTO importElementDTO) {
        final String projectId = importElementDTO.getProjectId();
        final String instanceId = importElementDTO.getInstanceId();
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(instance)) {
            log.error("导入配置模型查找失败:{}", instanceId);
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        ModelPropertyInfo importConfigModel = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId,
                instance,
                Stream.of(UMLDefinitionConstants.Design_Profile_MapToDataSource_url,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_sheet,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_firstCell,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_identificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_sourceIdentificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_targetIdentificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_mappingColumns,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_firstRowRepresentsHeading,
                        UMLDefinitionConstants.Design_Profile_ImportMap_targetScope,
                        UMLDefinitionConstants.Design_Profile_ImportMap_searchForElementsInTargetScopeOnly,
                        UMLDefinitionConstants.Design_Profile_ImportMap_searchForReferencesInTargetScopeOnly,
                        UMLDefinitionConstants.Design_Profile_ImportMap_importInstance,
                        UMLDefinitionConstants.Design_Profile_ImportMap_elementType,
                        UMLDefinitionConstants.Design_Profile_ImportMap_instanceClassifier,
                        UMLDefinitionConstants.Design_Profile_ImportMap_stereotypes).collect(Collectors.toList()));
        ImportConfigDTO importConfigDTO = new ImportConfigDTO();
        importConfigDTO.setProjectId(projectId);
        setMapToDataSourceProperty(importConfigDTO, importConfigModel);
        MetaClassInstance targetScope = importConfigModel.queryInstanceValue(UMLDefinitionConstants.Design_Profile_ImportMap_targetScope);
        if (Objects.nonNull(targetScope)) {
            log.info("目标范围模型id为：{}", targetScope.getId());
            importConfigDTO.setTargetScope(targetScope.getId());
        }
        importConfigDTO.setSearchForElementsInTargetScopeOnly(importConfigModel.queryBooleanValue(UMLDefinitionConstants.Design_Profile_ImportMap_searchForElementsInTargetScopeOnly));
        importConfigDTO.setSearchForReferencesInTargetScopeOnly(importConfigModel.queryBooleanValue(UMLDefinitionConstants.Design_Profile_ImportMap_searchForReferencesInTargetScopeOnly));
        importConfigDTO.setImportInstance(importConfigModel.queryBooleanValue(UMLDefinitionConstants.Design_Profile_ImportMap_importInstance));
        MetaClassInstance elementType = importConfigModel.queryInstanceValue(UMLDefinitionConstants.Design_Profile_ImportMap_elementType);
        if (Objects.nonNull(elementType)) {
            log.info("元素类型为：{}", elementType.getId());
            if (RelationConstraints.RELATION_TYPES.contains(elementType.getId())) {
                importConfigDTO.setRelationshipType(elementType.getId());
            } else {
                importConfigDTO.setElementType(elementType.getId());
            }
        }
        MetaClassInstance instanceClassifier = importConfigModel.queryInstanceValue(UMLDefinitionConstants.Design_Profile_ImportMap_instanceClassifier);
        if (Objects.nonNull(instanceClassifier)) {
            log.info("实例分类器类型为：{}", instanceClassifier.getId());
            importConfigDTO.setInstanceClassifier(instanceClassifier.getId());
        }
        importConfigDTO.setStereotypes(importConfigModel.queryListStringValue(UMLDefinitionConstants.Design_Profile_ImportMap_stereotypes));
        importConfigDTO.setAttachfileDir(importElementDTO.getAttachfileDir());
        importConfigDTO.setImportModelOwner(importElementDTO.getImportModelOwner());
        return importModelElement(importConfigDTO);
    }


    /**
     * desciption:Excel/CSV全局导入(直接导入或使用导入配置图批量导入)
     *
     * @param importConfigDTO
     * @return com.huawang.mdesign.model.service.vo.ImportInfoVo
     * @author lx
     * @date 2023/9/25
     */
    private ImportInfoVo importModelElement(ImportConfigDTO importConfigDTO) {
        String projectId = importConfigDTO.getProjectId();
        final Project project = projectManager.getValidProject(projectId);
        MetaClassInstance rootModel = internalUmlService.fetchInstance(project.getRootModel(), projectId);
        if (Objects.isNull(rootModel)) {
            log.error("项目根模型查找失败");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        LocalTransaction transaction = transactionService.createTransaction(
                projectId, IMPORT_EXCEL_TO_MODEL_ELEMENT);
        final ImportInfoVo importInfoVo = new ImportInfoVo();
        try {
            List<List<String>> importContentList = importPreProcess(projectId, importConfigDTO, importConfigDTO.getAttachfileDir(), importInfoVo);
            if (Objects.isNull(importConfigDTO.getRelationshipType()) || (BooleanUtils.isTrue(checkValidEnds(projectId, importConfigDTO, rootModel)))) {
                importHandle(projectId, importConfigDTO, importContentList, rootModel, importInfoVo);
            } else {
                importInfoVo.setFailElements(importContentList);
                importInfoVo.setOwner(importConfigDTO.getImportModelOwner());
                importInfoVo.setMetaClass(Stream.of(importConfigDTO.getElementType(),
                        importConfigDTO.getRelationshipType(),
                        importConfigDTO.getInstanceClassifier())
                        .filter(Objects::nonNull).findFirst().orElse(null));
            }
            transactionService.commit(projectId);
            InstanceVoUtils.fillModelResultVo(importInfoVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (RuntimeException e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.EXCEL_IMPORT_ERROR, e);
        }
        return importInfoVo;
    }

    /**
     * desciption:Excel/CSV表格导入
     *
     * @param diagramImportConfigDTO
     * @return com.huawang.mdesign.model.service.vo.ImportInfoVo
     * @author lx
     * @date 2023/9/25
     */
    private ImportInfoVo diagramImportModelElement(DiagramImportConfigDTO diagramImportConfigDTO) {

        String projectId = diagramImportConfigDTO.getProjectId();
        final Project project = projectManager.getValidProject(projectId);
        MetaClassInstance rootModel = internalUmlService.fetchInstance(project.getRootModel(), projectId);
        if (Objects.isNull(rootModel)) {
            log.error("项目根模型查找失败");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        LocalTransaction transaction = transactionService.createTransaction(
                projectId, IMPORT_EXCEL_TO_MODEL_ELEMENT);
        final ImportInfoVo importInfoVo = new ImportInfoVo();
        try {
            // 表格导入元素
            List<List<String>> importContentList = importPreProcess(projectId,
                    diagramImportConfigDTO,
                    diagramImportConfigDTO.getAttachfileDir(),
                    importInfoVo);
            if (BooleanUtils.isTrue(checkValidEnds(projectId, diagramImportConfigDTO, rootModel))) {
                digramImportHandle(projectId, diagramImportConfigDTO, importContentList, rootModel, importInfoVo);
            } else {
                importInfoVo.setFailElements(importContentList);
                importInfoVo.setOwner(diagramImportConfigDTO.getOwnerId());
                importInfoVo.setMetaClass(diagramImportConfigDTO.getMetaclassOrStereotype());
            }
            transactionService.commit(projectId);
            InstanceVoUtils.fillModelResultVo(importInfoVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (RuntimeException e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.EXCEL_IMPORT_ERROR, e);
        }
        return importInfoVo;
    }

    /**
     * desciption:导入前对关系两端类型进行校验:如果模型内两端不存在类型匹配的模型，则无需导入所有元素视为失败元素
     *
     * @param projectId
     * @param mapToDataSource
     * @param rootModel
     * @return java.lang.Boolean
     * @author lx
     * @date 2023/9/25
     */
    private Boolean checkValidEnds(String projectId, MapToDataSource mapToDataSource, MetaClassInstance rootModel) {

        final String sourceType = mapToDataSource.getSourceType();
        final String targetType = mapToDataSource.getTargetType();
        if (Objects.isNull(sourceType) && Objects.isNull(targetType)) {
            log.info("关系两端为空，不做校验");
            return true;
        }
        List<MetaClassInstance> childList = internalUmlService.getChildrenCascade(projectId, rootModel, false);
        if (CollectionUtils.isEmpty(childList)) {
            log.info("根节点下不存在模型");
            return false;
        }
        Map<String, Set<String>> givenTypes = internalUmlService.getGivenTypes(projectId, childList);
        final String sourceIdentificationProperty = mapToDataSource.getSourceIdentificationProperty();
        final String targetIdentificationProperty = mapToDataSource.getTargetIdentificationProperty();

        if (Objects.nonNull(sourceType)) {
            List<MetaClassInstance> sourceModel = childList.stream().filter(it -> givenTypes.get(it.getId()).contains(sourceType)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(sourceModel)) {
                log.info("根节点下关系来源端不存在匹配模型，导入数据全部失败");
                return false;
            }
            List<ModelPropertyInfo> sourceModelInfo = modelPropertyInfoService.createModelPropertyInfoList(projectId,
                    sourceModel,
                    Stream.of(sourceIdentificationProperty).collect(Collectors.toList()));
            List<Object> property = sourceModelInfo.stream().map(it -> it.queryProperty(sourceIdentificationProperty)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(property)) {
                return false;
            }
        }
        if (Objects.nonNull(targetType)) {
            List<MetaClassInstance> targetModel = childList.stream().filter(it -> givenTypes.get(it.getId()).contains(targetType)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(targetModel)) {
                log.info("根节点下关系目标端不存在匹配模型，导入数据全部失败");
                return false;
            }
            List<ModelPropertyInfo> targetModelInfo = modelPropertyInfoService.createModelPropertyInfoList(projectId,
                    targetModel,
                    Stream.of(targetIdentificationProperty).collect(Collectors.toList()));
            List<Object> property = targetModelInfo.stream().map(it -> it.queryProperty(targetIdentificationProperty)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(property)) {
                return false;
            }
        }
        return true;
    }

    /**
     * desciption:Excel/CSV导入数据预处理
     *
     * @param projectId
     * @param mapToDataSource
     * @param attachfileDir
     * @return java.util.List<java.util.List < java.lang.String>>
     * @author lx
     * @date 2023/9/25
     */
    private List<List<String>> importPreProcess(String projectId, MapToDataSource mapToDataSource, String attachfileDir, ImportInfoVo importInfoVo) {
        // 模型附件补充逻辑：
        String fileUrl = mapToDataSource.getFileUrl();
        MetaClassInstance attachFile = internalUmlService.fetchInstance(fileUrl, projectId);
        if (Objects.nonNull(attachFile)) {
            String attachFileName = internalUmlService.queryStringProperty(projectId, attachFile, UMLDefinitionConstants.Customization_AttachedFile_file);
            AttachFile stu = new Gson().fromJson(attachFileName, AttachFile.class);
            fileUrl = attachfileDir + File.separator + stu.getFilePath();
        }
        // 1.根据Sheet属性匹配Sheet：默认导入匹配的第一个Sheet
        List<SheetData> sheetDataList = importPreview(fileUrl);
        List<SheetData> importSheetDataList = sheetDataList.stream().filter(it -> Objects.equals(mapToDataSource.getSheet(), it.getSheetName()) ||
                Objects.isNull(it.getSheetName())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(importSheetDataList)) {
            return Collections.emptyList();
        }
        SheetData importSheetData = importSheetDataList.get(0);
        // 2.根据firstCell和FirstRowRepresentsHeading对contentList进行裁剪:1.导入起始位置 2.第一行是否是标题
        List<List<String>> contentList = importSheetData.getValues().stream().filter(content ->
                !content.stream().allMatch(it -> it.length() == 0)).collect(Collectors.toList());
        List<String> columns = importSheetData.getColumns();
        importInfoVo.setColumn(columns);

        if (CollectionUtils.isNotEmpty(columns)) {
            contentList.add(0, columns);
        }
        // 删除全为空的行
        String firstCell = mapToDataSource.getFirstCell();
        if (Objects.isNull(firstCell)) {
            log.error("不确定第一行导入元素");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        String[] firstColumn = firstCell.split("\\d");
        String[] firstRow = firstCell.split("\\D");
        if (Objects.equals(firstColumn.length, 0) || Objects.equals(firstRow.length, 0)) {
            log.error("首行或首列信息缺失");
            throw AbortExecutionException.build(ErrorCode.PARAM_ERROR);
        }
        int realFirstCell = BooleanUtils.isTrue(mapToDataSource.getFirstRowRepresentsHeading()) ?
                Integer.parseInt(String.join("", Arrays.asList(firstRow))) : Integer.parseInt(String.join("", Arrays.asList(firstRow))) - 1;
        int realColumn = convertLetterToNumber(firstColumn);
        // 裁剪列
        contentList = contentList.stream().map(it -> it.subList(realColumn, it.size())).collect(Collectors.toList());
        // 裁剪行
        return contentList.subList(realFirstCell, contentList.size());
    }

    private int convertLetterToNumber(String[] firstColumn) {
        int key = 65;
        int num = 0;
        for (String s : firstColumn) {
            num = num + s.charAt(0) - key;
        }
        return num;
    }

    /**
     * desciption:
     *
     * @param projectId
     * @param importConfigDTO
     * @param importContentList
     * @param rootModel
     * @param importInfoVo
     * @return void
     * @author lx
     * @date 2023/9/25
     */
    private void importHandle(String projectId,
                              ImportConfigDTO importConfigDTO,
                              List<List<String>> importContentList,
                              MetaClassInstance rootModel,
                              ImportInfoVo importInfoVo) {

        MiddleParamaters middleParameters = new MiddleParamaters();
        middleParameters.setProjectId(projectId);
        // 逆置列表：因为需要保存标识属性相同的最后一条数据
        Collections.reverse(importContentList);

        // 查询目标范围：1.筛选待修改模型 2.筛选对象属性
        MetaClassInstance targetScopeInstance = internalUmlService.fetchInstance(importConfigDTO.getTargetScope(), projectId);
        if (Objects.isNull(targetScopeInstance)) {
            log.error("目标范围模型读取异常,模型id为:{}", importConfigDTO.getTargetScope());
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        MetaClassInstance ownerInstance = internalUmlService.fetchInstance(importConfigDTO.getImportModelOwner(), projectId);
        if (Objects.isNull(ownerInstance)) {
            ownerInstance = targetScopeInstance;
        }

        // TODO：mof提供一个根据模型Name过滤的方法
        // 获取导入元素/引用元素模型
        List<MetaClassInstance> importElementChildList = BooleanUtils.isTrue(importConfigDTO.getSearchForElementsInTargetScopeOnly()) ?
                internalUmlService.getChildren(targetScopeInstance, false, projectId) :
                internalUmlService.getChildrenCascade(projectId, targetScopeInstance, false);
        if (!Objects.equals(targetScopeInstance.getId(), ownerInstance.getId())) {
            List<MetaClassInstance> ownerChildList = BooleanUtils.isTrue(importConfigDTO.getSearchForElementsInTargetScopeOnly()) ?
                    internalUmlService.getChildren(ownerInstance, false, projectId) :
                    internalUmlService.getChildrenCascade(projectId, ownerInstance, false);
            importElementChildList.addAll(ownerChildList);
        }

        List<MetaClassInstance> referencesElementChildList = BooleanUtils.isTrue(importConfigDTO.getSearchForReferencesInTargetScopeOnly()) ?
                internalUmlService.getChildren(targetScopeInstance, false, projectId) :
                internalUmlService.getChildrenCascade(projectId, rootModel, false)
                        .stream().filter(BusinessJudgeService::isCreatedInteractive).collect(Collectors.toList());

        Optional<String> result = Stream.of(importConfigDTO.getElementType(),
                importConfigDTO.getRelationshipType(),
                importConfigDTO.getInstanceClassifier())
                .filter(Objects::nonNull).findFirst();
        if (!result.isPresent()) {
            log.error("元素类型、关系类型与分类器类型均为空");
            throw AbortExecutionException.build(ErrorCode.INSTANCE_TYPE_ERROR);
        }
        // 实例分类器是否为空：1.为空：则导入的为元素或关系 2.不为空：则导入的类型为实例规格
        String metaClassOrStereotype = Objects.nonNull(importConfigDTO.getInstanceClassifier()) ?
                UMLDefinitionConstants.InstanceSpecification : result.get();
        // 查找元类 && 添加构造型
        List<String> stereotypes = CollectionUtils.isEmpty(importConfigDTO.getStereotypes()) ?
                new ArrayList<>() : importConfigDTO.getStereotypes();
        String metaClass = findRealMetaClass(projectId, metaClassOrStereotype, stereotypes);
        middleParameters.setMetaClass(metaClass);
        // columnInfo注入<Index索引, 属性key>
        List<ColumnInfo> columnInfoList = createColumnInfoList(importConfigDTO, metaClassOrStereotype, referencesElementChildList);
        if (CollectionUtils.isEmpty(columnInfoList)) {
            log.error("拆分后属性映射列为空");
            throw AbortExecutionException.build(ErrorCode.PROPERTY_UPDATE_ERROR);
        }

        middleParameters.setColumnInfoList(columnInfoList);
        // 获取identityColumnInfo 和 identityIndex
        final String identificationProperty = importConfigDTO.getIdentificationProperty();
        if (Objects.isNull(identificationProperty)) {
            log.error("标识属性不存在");
            throw AbortExecutionException.build(ErrorCode.PROPERTY_QUERY_ERROR);
        }
        ColumnInfo identityColumnInfo = new ColumnInfo();
        Optional<ColumnInfo> identityColumnInfoResult = columnInfoList.stream().filter(it ->
                Objects.equals(it.getKey(), identificationProperty) &&
                        Objects.equals(it.getPropertyType(), 0)).findFirst();
        if (identityColumnInfoResult.isPresent()) {
            identityColumnInfo = identityColumnInfoResult.get();
        }

        middleParameters.setIdentityColumnInfo(identityColumnInfo);
        int identityIndex = columnInfoList.indexOf(identityColumnInfo);
        middleParameters.setIdentityIndex(identityIndex);
        List<ExistElement> existElementsForAdd = createExistModelsForAdd(importConfigDTO,
                identityColumnInfo,
                importElementChildList,
                metaClass,
                stereotypes);
        middleParameters.setExistElementsForAdd(existElementsForAdd);

        // 对importContentList遍历两次:1. 保存标识属性相同的最后一条数据 2.第二次:使用existElementsForAdd进行校验数据是否存在,并生成AddModel指令和updateModelList
        // 1.第一次循环：保存重复数据，并移除
        removeRepeatContent(importInfoVo, importContentList, identityIndex);
        Collections.reverse(importContentList);
        middleParameters.setImportContentList(importContentList);
        middleParameters.setStereotypes(stereotypes);
        middleParameters.setMetaClassOrSereotypes(metaClassOrStereotype);
        middleParameters.setOwnerInstance(ownerInstance);
        middleParameters.setReferencesElementChildList(referencesElementChildList);

        List<MetaClassInstance> updateModelList;
        if (Objects.nonNull(importConfigDTO.getInstanceClassifier())) {
            MetaClassInstance classfier = internalUmlService.fetchInstance(importConfigDTO.getInstanceClassifier(), projectId);
            middleParameters.setClassiferList(Collections.singletonList(classfier));
            updateModelList = importDataService.createInstanceSpecification(importInfoVo, importContentList, middleParameters);
        } else if (Objects.nonNull(importConfigDTO.getElementType())) {
            updateModelList = importDataService.createElement(importInfoVo, importContentList, middleParameters);
        } else {
            middleParameters.setMapToDataSource(importConfigDTO);
            updateModelList = importDataService.createRelationship(importInfoVo, importContentList, middleParameters);
        }

        if (!Objects.equals(updateModelList.size(), importContentList.size())) {
            log.error("模型更新列表与过滤后导入内容行数量不一致");
            throw AbortExecutionException.build(ErrorCode.ROW_NUMBER_ERROR);
        }

        // 1.BatchCommand:更新模型可能涉及到的增删改指令
        fetchAndExecuteBatchCommand(projectId, importContentList, updateModelList, columnInfoList);

        importInfoVo.setOwner(importConfigDTO.getImportModelOwner());
        importInfoVo.setMetaClass(metaClassOrStereotype);
        importInfoVo.setImportInstance(importConfigDTO.getImportInstance());
    }

    private void digramImportHandle(String projectId,
                                    DiagramImportConfigDTO diagramImportConfigDTO,
                                    List<List<String>> importContentList,
                                    MetaClassInstance rootModel,
                                    ImportInfoVo importInfoVo) {
        // 逆置列表：因为需要保存标识属性相同的最后一条数据
        Collections.reverse(importContentList);
        // 获取导入元素/引用元素模型
        MetaClassInstance diagramInstance = internalUmlService.fetchInstance(diagramImportConfigDTO.getInstanceId(), projectId);
        if (Objects.isNull(diagramInstance)) {
            log.error("表格模型查找失败,id为{}", diagramImportConfigDTO.getInstanceId());
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        // 查询父节点并将其子节点全部加入表格中
        ModelPropertyInfo diagramModelProperty = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId, diagramInstance,
                Stream.of(UMLDefinitionConstants.Element_owner,
                        UMLDefinitionConstants.TableAndMatrix_DiagramTable_scope,
                        UMLDefinitionConstants.TableAndMatrix_DiagramTable_additionalElements).collect(Collectors.toList()));
        MetaClassInstance diagramOwner = diagramModelProperty.queryInstanceValue(UMLDefinitionConstants.Element_owner);
        if (Objects.isNull(diagramOwner)) {
            log.error("表格模型父查找失败");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        List<MetaClassInstance> diagramScope = diagramModelProperty.queryListInstanceValue(UMLDefinitionConstants.TableAndMatrix_DiagramTable_scope);
        MetaClassInstance importModelOwner = CollectionUtils.isNotEmpty(diagramScope) ?
                diagramScope.get(0) : diagramOwner;
        MetaClassInstance validOwnerInstance = internalUmlService.fetchInstance(diagramImportConfigDTO.getOwnerId(), projectId);
        if (Objects.nonNull(validOwnerInstance)) {
            importModelOwner = validOwnerInstance;
        }

        List<MetaClassInstance> diagramOwnerChildList = internalUmlService.getChildren(diagramOwner, false, projectId);
        // 获取表格行元素
        List<String> rowElements = diagramTableService.queryRowElements(projectId, diagramImportConfigDTO.getInstanceId());
        List<MetaClassInstance> diagramChildList = CollectionUtils.isEmpty(internalUmlService.fetchInstanceByIds(rowElements, projectId)) ?
                new ArrayList<>() : internalUmlService.fetchInstanceByIds(rowElements, projectId);
        Set<MetaClassInstance> importElementChildList = new HashSet<>();
        importElementChildList.addAll(diagramOwnerChildList);
        importElementChildList.addAll(diagramChildList);
        List<MetaClassInstance> referencesElementChildList = internalUmlService.getChildrenCascade(projectId, rootModel, false)
                .stream().filter(BusinessJudgeService::isCreatedInteractive).collect(Collectors.toList());

        //1. metaClass:真正元类  2. stereotypes:构造型
        List<MetaClassInstance> classifierList = new ArrayList<>();
        String metaclassOrStereotype;
        if (internalUmlService.checkInstanceType(projectId, diagramInstance, UMLDefinitionConstants.TableAndMatrix_InstanceTable)) {
            metaclassOrStereotype = UMLDefinitionConstants.InstanceSpecification;
            MetaClassInstance classifier = internalUmlService.fetchInstance(diagramImportConfigDTO.getMetaclassOrStereotype(), projectId);
            classifierList = Collections.singletonList(classifier);
        } else {
            metaclassOrStereotype = diagramImportConfigDTO.getMetaclassOrStereotype();
        }
        List<String> stereotypes = new ArrayList<>();
        String metaClass = findRealMetaClass(projectId, metaclassOrStereotype, stereotypes);

        List<ColumnInfo> columnInfoList = createColumnInfoList(diagramImportConfigDTO, metaclassOrStereotype, referencesElementChildList);
        if (CollectionUtils.isEmpty(columnInfoList)) {
            log.error("拆分后属性映射列为空");
            throw AbortExecutionException.build(ErrorCode.PROPERTY_UPDATE_ERROR);
        }

        final String identificationProperty = diagramImportConfigDTO.getIdentificationProperty();
        if (Objects.isNull(identificationProperty)) {
            log.error("标识属性不存在");
            throw AbortExecutionException.build(ErrorCode.PROPERTY_QUERY_ERROR);
        }
        ColumnInfo identityColumnInfo = new ColumnInfo();
        Optional<ColumnInfo> identityColumnInfoResult = columnInfoList.stream().filter(it ->
                Objects.equals(it.getKey(), identificationProperty)).findFirst();
        if (identityColumnInfoResult.isPresent()) {
            identityColumnInfo = identityColumnInfoResult.get();
        }
        int identityIndex = columnInfoList.indexOf(identityColumnInfo);
        List<ExistElement> existElementsForAdd = createExistModelsForAdd(diagramImportConfigDTO,
                identityColumnInfo,
                new ArrayList<>(importElementChildList),
                metaClass,
                stereotypes);
        // 对importContentList遍历2次:1.保存标识属性相同的最后一条数据 2.第二次:使用existElementsForAdd进行校验数据是否存在,并生成AddModel指令和updateModelList
        // 1.第一次循环：保存重复数据，并移除
        removeRepeatContent(importInfoVo, importContentList, identityIndex);
        Collections.reverse(importContentList);

        MiddleParamaters middleParamaters = new MiddleParamaters();
        middleParamaters.setProjectId(projectId);
        middleParamaters.setImportContentList(importContentList);
        middleParamaters.setIdentityIndex(identityIndex);
        middleParamaters.setColumnInfoList(columnInfoList);
        middleParamaters.setExistElementsForAdd(existElementsForAdd);
        middleParamaters.setIdentityColumnInfo(identityColumnInfo);
        middleParamaters.setMetaClass(metaClass);
        middleParamaters.setStereotypes(stereotypes);
        middleParamaters.setMetaClassOrSereotypes(metaclassOrStereotype);
        middleParamaters.setOwnerInstance(importModelOwner);
        middleParamaters.setReferencesElementChildList(referencesElementChildList);

        List<MetaClassInstance> updateModelList;
        if (Objects.equals(metaclassOrStereotype, UMLDefinitionConstants.InstanceSpecification)) {
            middleParamaters.setClassiferList(classifierList);
            updateModelList = importDataService.createInstanceSpecification(importInfoVo, importContentList, middleParamaters);
        } else if (RelationConstraints.RELATION_TYPES.contains(metaClass)) {
            middleParamaters.setMapToDataSource(diagramImportConfigDTO);
            updateModelList = importDataService.createRelationship(importInfoVo, importContentList, middleParamaters);
        } else {
            updateModelList = importDataService.createElement(importInfoVo, importContentList, middleParamaters);
        }
        if (!Objects.equals(updateModelList.size(), importContentList.size())) {
            log.error("模型更新列表与过滤后导入内容行数量不一致");
            throw AbortExecutionException.build(ErrorCode.ROW_NUMBER_ERROR);
        }

        // BatchCommand:更新模型可能涉及到的增删改指令
        fetchAndExecuteBatchCommand(projectId, importContentList, updateModelList, columnInfoList);
        // 避免更新的模型重复添加至表格行元素
        updateModelList.forEach(it -> {
            if (!diagramChildList.contains(it)) {
                diagramChildList.add(it);
            }
        });
        umlService.updateModel(projectId, diagramInstance.getId(), UMLDefinitionConstants.TableAndMatrix_DiagramTable_rowElements,
                diagramChildList);

        // 表格导入后置处理:importElementChildList为表格中有excel没有的元素
        diagramChildList.removeAll(updateModelList);
        importInfoVo.setOwner(importModelOwner.getId());
        importInfoVo.setMetaClass(diagramImportConfigDTO.getMetaclassOrStereotype());
        if (CollectionUtils.isEmpty(diagramChildList)) {
            return;
        }
        if (Objects.equals(diagramImportConfigDTO.getDeleteRowOption(), REMOVE_FROM_DIAGRAM)) {
            umlService.updateModel(projectId, diagramInstance.getId(), UMLDefinitionConstants.TableAndMatrix_DiagramTable_rowElements,
                    updateModelList);
            importInfoVo.setRemoveElements(diagramChildList.stream().map(MetaClassInstance::getId).collect(Collectors.toList()));
            // 移除表格额外元素
            umlService.removeModel(projectId, diagramInstance.getId(), UMLDefinitionConstants.TableAndMatrix_DiagramTable_additionalElements);
        } else if (Objects.equals(diagramImportConfigDTO.getDeleteRowOption(), DELETE_MODEL)) {
            umlService.deleteModels(projectId, diagramChildList.stream().map(MetaClassInstance::getId).collect(Collectors.toList()));
            importInfoVo.setRemoveElements(diagramChildList.stream().map(MetaClassInstance::getId).collect(Collectors.toList()));
        } else {
            log.info("不对表格内数据做特殊处理");
        }
    }

    /**
     * desciption:创建属性信息列：key(属性)、dateType(属性类型)、existElementList(该属性过滤出符合条件的模型Map：决定该模型的值能否更新)
     *
     * @param mapToDataSource
     * @param metaclassOrStereotype
     * @param referencesElementChildList
     * @return java.util.List<com.huawang.mdesign.model.service.dto.ColumnInfo>
     * @author lx
     * @date 2023/9/25
     */
    private List<ColumnInfo> createColumnInfoList(MapToDataSource mapToDataSource,
                                                  String metaclassOrStereotype,
                                                  List<MetaClassInstance> referencesElementChildList) {
        // TODO：后续要过滤引用元素类型直接在此查询referencesGivenTypes
        final String projectId = mapToDataSource.getProjectId();
        List<ModelPropertyInfo> existModelInfos = modelPropertyInfoService.createModelPropertyInfoList(projectId,
                referencesElementChildList, Stream.of(UMLDefinitionConstants.NamedElement_name).collect(Collectors.toList()));
        // columnInfo注入<Index索引, 属性key>
        List<String> mappingColumnInfoList = mapToDataSource.getMappingColumns();
        if (CollectionUtils.isEmpty(mappingColumnInfoList)) {
            log.error("导入属性映射为空");
            throw AbortExecutionException.build(ErrorCode.PROPERTY_UPDATE_ERROR);
        }
        List<ColumnInfo> columnInfoList = initColumnInfoList(projectId, mappingColumnInfoList);
        // columnInfo注入注入<属性类型>
        QueryPropertyConfigDTO queryPropertyConfigDTO = new QueryPropertyConfigDTO();
        queryPropertyConfigDTO.setProjectId(projectId);
        queryPropertyConfigDTO.setInstanceId(metaclassOrStereotype);
        queryPropertyConfigDTO.setKeys(columnInfoList.stream().map(ColumnInfo::getKey).filter(Objects::nonNull).collect(Collectors.toList()));
        List<PropertyConfig> propertyConfigList = modelService.queryPropertyListBatchByKeys(queryPropertyConfigDTO);
        List<MetaClassInstance> propertyInstances =
                internalUmlService.fetchInstanceByIds(queryPropertyConfigDTO.getKeys(),
                        projectId);
        Map<String, List<ItemInfo>> itemInfoMap = internalPropertyService.queryItemInfo(projectId, propertyInstances);
        Map<String, MetaClassInstance> itemInstanceMap =
                internalUmlService.fetchInstances(itemInfoMap.values().stream().filter(Objects::nonNull).flatMap(Collection::stream).map(ItemInfo::getValue).collect(Collectors.toList()), projectId);
        for (ColumnInfo columnInfo : columnInfoList) {
            Optional<PropertyConfig> result = propertyConfigList.stream().filter(it ->
                    Objects.equals(columnInfo.getKey(), it.getKey()))
                    .findFirst();
            if (!result.isPresent()) {
                log.info("无法查到key的数据类型,key为{}", columnInfo.getKey());
                continue;
            }
            PropertyConfig propertyConfig = result.get();
            String dataType = propertyConfig.getDataType();
            columnInfo.setDataType(dataType);
            columnInfo.setIsMultiplicity(propertyConfig.getIsMultiplicity());
            if (Objects.equals(dataType, TypeEnum.INSTANCE.getName())) {
                // 如果Items有值，则为枚举值/如果无值，则筛选模型

                if (CollectionUtils.isNotEmpty(itemInfoMap.get(columnInfo.getKey()))) {
                    PropertyConfigItem propertyConfigItem =
                            modelManagerConfig.getPropertyConfigItems().get(columnInfo.getKey());
                    final List<ItemInfo> itemInfos;
                    if (propertyConfigItem != null && CollectionUtils.isNotEmpty(propertyConfigItem.getItems())) {
                        itemInfos = propertyConfigItem.getItems();
                    } else {
                        itemInfos = itemInfoMap.get(columnInfo.getKey());
                    }

                    itemInfos.forEach(it -> {
                        ExistElement existElement = new ExistElement();
                        existElement.setIdentityName(it.getLabel());
                        existElement.setModel(itemInstanceMap.get(it.getValue()));
                        columnInfo.getExistElementList().add(existElement);
                    });
                    log.info("设置枚举值:{}", itemInfos);
                } else {
                    // 通过key得到moreBtnCondition，再通过moreBtnCondition筛选
                    if (CollectionUtils.isNotEmpty(existModelInfos)) {
                        existModelInfos.forEach(it -> {
                            ExistElement existElement = new ExistElement();
                            existElement.setIdentityName(it.queryStringValue(UMLDefinitionConstants.NamedElement_name));
                            existElement.setModel(it.getInstance());
                            columnInfo.getExistElementList().add(existElement);
                        });
                    }
                }
            }
        }
        return columnInfoList;
    }


    private List<ColumnInfo> initColumnInfoList(String projectId, List<String> mappingColumnInfoList) {
        return mappingColumnInfoList.stream().map(it -> {
            ColumnInfo columnInfo = new ColumnInfo();
            String[] mappingColumn = it.split(SystemConstants.MAPPING_COLUMNS_SEPARATOR);
            if (!Objects.equals(mappingColumn.length, 2)) {
                return columnInfo;
            }
            String[] modelPropertyGroup = mappingColumn[1].split(SystemConstants.MODEL_PROPERTY_SEPARATOR);
            // 特殊拼接的属性列:1.关系两端属性 2.分类器的模型属性
            if (Objects.equals(modelPropertyGroup.length, 2)) {
                if (Objects.equals(modelPropertyGroup[0], "source")) {
                    columnInfo.setPropertyType(1);
                    columnInfo.setKey(modelPropertyGroup[1]);
                    columnInfo.setIsSource(true);
                } else if (Objects.equals(modelPropertyGroup[0], "target")) {
                    columnInfo.setPropertyType(1);
                    columnInfo.setKey(modelPropertyGroup[1]);
                    columnInfo.setIsSource(false);
                } else {
                    columnInfo.setPropertyType(2);
                    Map<String, MetaClassInstance> modelPropertyMap = internalUmlService.fetchInstances(Arrays.asList(modelPropertyGroup), projectId);
                    columnInfo.setClassifier(modelPropertyMap.get(modelPropertyGroup[0]));
                    columnInfo.setClassifierProperty(modelPropertyMap.get(modelPropertyGroup[1]));
                }
            } else {
                columnInfo.setPropertyType(0);
                columnInfo.setKey(modelPropertyGroup[0]);
            }
            return columnInfo;
        }).collect(Collectors.toList());
    }


    /**
     * desciption:创建符合标识属性条件的存在模型列表：决定后续数据是否新增模型
     *
     * @param mapToDataSource
     * @param identityColumnInfo
     * @param importElementChildList
     * @param metaClass
     * @return java.util.List<com.huawang.mdesign.model.service.dto.ExistElement>
     * @author lx
     * @date 2023/9/26
     */
    private List<ExistElement> createExistModelsForAdd(MapToDataSource mapToDataSource,
                                                       ColumnInfo identityColumnInfo,
                                                       List<MetaClassInstance> importElementChildList,
                                                       String metaClass,
                                                       List<String> stereotypes) {
        final String projectId = mapToDataSource.getProjectId();
        String identificationProperty = mapToDataSource.getIdentificationProperty();
        String identificationPropertyType = identityColumnInfo.getDataType();

        importElementChildList = importElementChildList.stream().filter(it ->
                Objects.equals(it.getMetaClass().getId(), metaClass) &&
                        Objects.equals(it.getAppliedStereotypes(), stereotypes)).collect(Collectors.toList());


        List<ModelPropertyInfo> existModelForAddInfos = modelPropertyInfoService.createModelPropertyInfoList(projectId,
                importElementChildList, Stream.of(identificationProperty).collect(Collectors.toList()));
        List<ExistElement> existElementsForAdd = new ArrayList<>();
        if (Objects.equals(identificationPropertyType, TypeEnum.STRING.getName())) {
            existModelForAddInfos.forEach(it -> {
                ExistElement existElement = new ExistElement();
                existElement.setIdentityName(it.queryStringValue(identificationProperty));
                existElement.setModel(it.getInstance());
                existElementsForAdd.add(existElement);
            });
        } else if (Objects.equals(identificationPropertyType, TypeEnum.INSTANCE.getName())) {

            List<MetaClassInstance> models = existModelForAddInfos.stream().map(it -> it.queryInstanceValue(identificationProperty)).
                    filter(Objects::nonNull).collect(Collectors.toList());
            Map<String, ModelPropertyInfo> propertyInstanceInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId,
                    models, Stream.of(UMLDefinitionConstants.NamedElement_name).collect(Collectors.toList()));
            existModelForAddInfos.forEach(it -> {
                ExistElement existElement = new ExistElement();
                MetaClassInstance propertyInstance = it.queryInstanceValue(identificationProperty);
                if (Objects.isNull(propertyInstance)) {
                    log.info("对象标识属性为空");
                    return;
                }
                ModelPropertyInfo propertyInstanceInfo = propertyInstanceInfoMap.get(propertyInstance.getId());
                existElement.setIdentityName(propertyInstanceInfo.queryStringValue(UMLDefinitionConstants.NamedElement_name));
                existElement.setModel(it.getInstance());
                existElementsForAdd.add(existElement);
            });
        } else if (Objects.equals(identificationPropertyType, TypeEnum.BOOLEAN.getName())) {
            existModelForAddInfos.forEach(it -> {
                ExistElement existElement = new ExistElement();
                existElement.setIdentityName(String.valueOf(it.queryBooleanValue(identificationProperty)));
                existElement.setModel(it.getInstance());
            });
        } else {
            log.warn("标识属性类型不为String、Instance或boolean值");
        }
        return existElementsForAdd;

    }

    /**
     * desciption:查找metaClassOrStereotype的真正元类，并将构造型添加至stereotypes
     *
     * @param projectId
     * @param metaClassOrStereotype
     * @param stereotypes
     * @return java.lang.String
     * @author lx
     * @date 2023/9/25
     */
    private String findRealMetaClass(String projectId, String metaClassOrStereotype, List<String> stereotypes) {
        // 注入模型metaClass
        MetaClassInstance metaClassOrStereotypeInstance = internalUmlService.fetchInstance(metaClassOrStereotype, projectId);
        if (Objects.isNull(metaClassOrStereotypeInstance)) {
            log.error("元类模型查找失败");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        if (!BooleanUtils.isTrue(internalUmlService.isOnlyMetaClass(projectId, metaClassOrStereotypeInstance))) {
            List<String> metaClassList = internalUmlService.getSelfBasePropertyList(projectId,
                    metaClassOrStereotypeInstance);
            if (CollectionUtils.isEmpty(metaClassList)) {
                log.error("构造型找不到元类");
                throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
            }
            stereotypes.add(0, metaClassOrStereotype);
            metaClassOrStereotype = metaClassList.get(0);
        }
        return metaClassOrStereotype;
    }

    @NotNull
    private void fetchAndExecuteBatchCommand(String projectId,
                                             List<List<String>> importContentList,
                                             List<MetaClassInstance> updateModelList,
                                             List<ColumnInfo> columnInfoList) {
        BatchCommand batchCommand = new BatchCommand();
        Map<Integer, IUpdateProperty> propertyMethodNameMap = initPropertyMethodMap(columnInfoList);

        for (List<String> importContent : importContentList) {
            int row = importContentList.indexOf(importContent);
            MetaClassInstance updateModel = updateModelList.get(row);
            for (ColumnInfo columnInfo : columnInfoList) {
                Integer column = getColumn(importContentList, columnInfoList, row, columnInfo);

                if (column == null) {
                    continue;
                }
                String data = importContentList.get(row).get(column);
                ModifyPropertyDTO modifyPropertyDTO = createModifyPropertyDTO(projectId, data, columnInfo, updateModel);
                IUpdateProperty updateProperty = propertyMethodNameMap.get(column);
                BatchCommand tempBatchCommand = createBatchCommand(projectId, data, columnInfo, updateModel, modifyPropertyDTO, updateProperty);
                batchCommand.mergeCommand(tempBatchCommand);
            }
        }

        // 批量新增
        if (CollectionUtils.isNotEmpty(batchCommand.getAddModelDTOList())) {
            umlService.addModel(batchCommand.getAddModelDTOList());
        }
        // 批量追加
        umlService.appendModelByBatch(projectId, batchCommand.getAppendModelDTOList());
        // 批量更新
        umlService.updateModelByBatch(batchCommand.getUpdateModelDTOList());
        // 批量移除
        umlService.removeModelByBatch(projectId, batchCommand.getRemoveModelDTOList());
        // 批量删除
        umlService.deleteModels(projectId, batchCommand.getDeleteModelDTOList()
                .stream().flatMap(it -> it.getIds().stream()).collect(Collectors.toSet()));
    }

    @Nullable
    private Integer getColumn(List<List<String>> importContentList, List<ColumnInfo> columnInfoList, int row, ColumnInfo columnInfo) {
        if (!Objects.equals(columnInfo.getPropertyType(), 0)) {
            return null;
        }
        int column = columnInfoList.indexOf(columnInfo);
        if (column >= importContentList.get(row).size()) {
            log.error("文件列数目与配置列数目不匹配, 文件列数目:{}, 模型列数目:{}, 模型列id:{}", importContentList.get(row).size(),
                    columnInfoList.size(),
                    columnInfo.getKey());
            return null;
        }
        return column;
    }

    private Map<Integer, IUpdateProperty> initPropertyMethodMap(List<ColumnInfo> columnInfoList) {
        Map<Integer, IUpdateProperty> propertyMethodNameMap = new HashMap<>(columnInfoList.size());
        for (int i = 0; i < columnInfoList.size(); i++) {
            ColumnInfo columnInfo = columnInfoList.get(i);
            String methodName = propertyManager.getPropertyMethodName(columnInfo.getKey(), UPDATE_PREFIX, null);
            IUpdateProperty updateProperty = updatePropertyFactory.getOperation(methodName);
            propertyMethodNameMap.put(i, updateProperty);
        }
        return propertyMethodNameMap;
    }

    @Nullable
    private BatchCommand createBatchCommand(String projectId,
                                            String data,
                                            ColumnInfo columnInfo,
                                            MetaClassInstance updateModel,
                                            ModifyPropertyDTO modifyPropertyDTO,
                                            IUpdateProperty updateProperty) {
        if (CollectionUtils.isEmpty(modifyPropertyDTO.getValue())) {
            // 如果value值不存在，则跳过无需更新
            return null;
        }
        BatchCommand batchCommand = null;
        // 特殊处理updateValueByBatch的默认返回null, 实现过的返回BatchCommand对象
        if (Objects.nonNull(updateProperty)) {
            batchCommand = updateProperty.updateValueByBatch(modifyPropertyDTO);
        }
        // 无需特殊处理或未实现过的更新逻辑得到的batchCommand为null, 此时直接生成Update指令
        if (Objects.isNull(batchCommand)) {
            batchCommand = new BatchCommand();
            UpdateModelDTO updateModelDTO = createUpdateModelDTO(projectId, data, columnInfo, updateModel);
            batchCommand.appendUpdateModelDto(updateModelDTO);
        }
        return batchCommand;
    }

    @NotNull
    private ModifyPropertyDTO createModifyPropertyDTO(@NotNull String projectId,
                                                      @Nullable String data,
                                                      @NotNull ColumnInfo columnInfo,
                                                      @NotNull MetaClassInstance updateModel) {
        ModifyPropertyDTO modifyPropertyDTO = new ModifyPropertyDTO();
        modifyPropertyDTO.setProjectId(projectId);
        modifyPropertyDTO.setInstanceId(updateModel.getId());
        modifyPropertyDTO.setDataType(columnInfo.getDataType());
        modifyPropertyDTO.setIsMultiplicity(columnInfo.getIsMultiplicity());
        modifyPropertyDTO.setKey(columnInfo.getKey());
        List<Object> value = Objects.isNull(parseData(data, columnInfo)) ?
                Collections.emptyList() : Collections.singletonList(parseData(data, columnInfo));
        modifyPropertyDTO.setValue(value);
        return modifyPropertyDTO;
    }

    /**
     * description: 读取的excel数据均转化为字符串类型
     */
    @Nullable
    private Object parseData(@Nullable String data, @NotNull ColumnInfo columnInfo) {
        if (data == null || data.length() == 0) {
            return null;
        }
        String dataType = columnInfo.getDataType();
        if (Objects.equals(dataType, TypeEnum.STRING.getName())) {
            return data;
        } else if (Objects.equals(dataType, TypeEnum.BOOLEAN.getName())) {
            boolean isBooleanData = BooleanUtils.isTrue(data.equalsIgnoreCase(String.valueOf(true)))
                    || BooleanUtils.isTrue(data.equalsIgnoreCase(String.valueOf(false)));
            // 如果是忽略大小写的boolean类型数据，则转化; 否则跳过
            return isBooleanData ? Boolean.parseBoolean(data) : null;
        } else if (Objects.equals(dataType, TypeEnum.INSTANCE.getName())) {
            List<ExistElement> existElementList = columnInfo.getExistElementList();
            if (CollectionUtils.isEmpty(existElementList)) {
                log.info("{}属性列不存在匹配模型", columnInfo.getKey());
                return null;
            }
            Optional<ExistElement> existElement = existElementList.stream().filter(it -> Objects.equals(it.getIdentityName(), data)).findFirst();
            if (existElement.isPresent()) {
                return existElement.get().getModel().getId();
            }
        } else {
            return null;
        }

        return null;
    }

    /**
     * desciption:根据ColumnInfo中的existModels属性为导入文件的每条数据创建updateModelDTO
     *
     * @param projectId
     * @param data
     * @param columnInfo
     * @param updateModel
     * @return com.huawang.mdesign.model.service.dto.UpdateModelDTO
     * @author lx
     * @date 2023/9/25
     */
    private UpdateModelDTO createUpdateModelDTO(String projectId, String data, ColumnInfo columnInfo, MetaClassInstance updateModel) {

        if (Objects.equals(columnInfo.getDataType(), TypeEnum.STRING.getName())) {
            // 如果属性为String类型，直接暴力更新
            return BooleanUtils.isTrue(columnInfo.getIsMultiplicity()) ?
                    UpdateModelFactory.newInstance(projectId, updateModel.getId(), columnInfo.getKey(), Collections.singletonList(data)) :
                    UpdateModelFactory.newInstance(projectId, updateModel.getId(), columnInfo.getKey(), data);
        } else if (Objects.equals(columnInfo.getDataType(), TypeEnum.BOOLEAN.getName())) {
            if (BooleanUtils.isTrue(data.equalsIgnoreCase(String.valueOf(true))) ||
                    BooleanUtils.isTrue(data.equalsIgnoreCase(String.valueOf(false)))) {
                return UpdateModelFactory.newInstance(projectId, updateModel.getId(), columnInfo.getKey(), Boolean.parseBoolean(data));
            }
        } else if (Objects.equals(columnInfo.getDataType(), TypeEnum.INSTANCE.getName())) {
            List<ExistElement> existElementList = columnInfo.getExistElementList();
            if (CollectionUtils.isEmpty(existElementList)) {
                log.info("{}属性列不存在匹配模型", columnInfo.getKey());
                return null;
            }
            Optional<ExistElement> existElement = existElementList.stream().filter(it -> Objects.equals(it.getIdentityName(), data)).findFirst();
            if (existElement.isPresent()) {
                return BooleanUtils.isTrue(columnInfo.getIsMultiplicity()) ?
                        UpdateModelFactory.newInstance(projectId, updateModel.getId(), columnInfo.getKey(), Collections.singletonList(existElement.get().getModel())) :
                        UpdateModelFactory.newInstance(projectId, updateModel.getId(), columnInfo.getKey(), existElement.get().getModel());
            }
        } else {
            log.warn("属性列数据类型不为String、Instance或Boolean");
        }
        return null;
    }

    private void removeRepeatContent(ImportInfoVo importInfoVo, List<List<String>> importContentList, int identityIndex) {
        List<String> existContent = new ArrayList<>();
        List<List<String>> existContentList = new ArrayList<>();
        List<List<String>> repeatContentList = new ArrayList<>();
        for (List<String> importContent : importContentList) {
            int i = importContentList.indexOf(importContent);
            String data = importContentList.get(i).get(identityIndex);
            // 如果包含，移除数据;如果不包含，则新增存在已存在数据
            if (existContent.contains(data)) {
                repeatContentList.add(importContent);
            } else {
                existContent.add(data);
                existContentList.add(importContent);
            }
        }
        // 移除重复数据
        importInfoVo.getFailElements().addAll(repeatContentList);
        // 保存不重复数据
        importContentList.clear();
        importContentList.addAll(existContentList);
    }

    /**
     * desciption:创建导入配置图：1.target模型为package：创建导入配置图 2.target模型为ImportMap：直接覆盖
     *
     * @param importConfigDTO
     * @return com.huawang.mdesign.model.service.vo.ModelResultVo
     * @author lx
     * @date 2023/9/25
     */
    public ModelResultVo createImportConfig(ImportConfigDTO importConfigDTO) {

        final String projectId = importConfigDTO.getProjectId();
        ModelResultVo modelResultVo = new ModelResultVo();
        MetaClassInstance target = internalUmlService.fetchInstance(importConfigDTO.getTargetId(), projectId);
        if (Objects.isNull(target)) {
            log.error("文件模型 或 导入配置图模型不存在");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }


        LocalTransaction transaction = transactionService.createTransaction(projectId, ADD_MODEL);
        try {
            MetaClassInstance result;
            if (internalUmlService.checkInstanceType(projectId, target, UMLDefinitionConstants.Design_Profile_ImportMap)) {
                result = target;
            } else {
                CommandParameter parameter = CommandParameter.builder()
                        .type(CommandAddType.initCommitStatus(0))
                        .typeId(UMLDefinitionConstants.Class)
                        .projectId(projectId)
                        .instanceId(ModelConstantURI.initInstanceId(projectId))
                        .parentId(importConfigDTO.getTargetId())
                        .applyStereotypes(Stream.of(UMLDefinitionConstants.Design_Profile_ImportMap,
                                UMLDefinitionConstants.Design_Profile_MapToDataSource).collect(Collectors.toList()))
                        .build();
                result = umlService.addModel(parameter);
            }
            importConfigSetProperties(importConfigDTO, result);
            transactionService.commit(projectId);
            modelResultVo.setInstanceId(result.getId());
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (RuntimeException e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.SERVICE_ERROR, e);
        }
        return modelResultVo;
    }

    public ModelResultVo updateImportConfig(UpdateImportConfigDTO updateImportConfigDTO) {
        final String projectId = updateImportConfigDTO.getProjectId();
        final MetaClassInstance instance = internalUmlService.fetchInstance(updateImportConfigDTO.getInstanceId(), projectId);
        if (Objects.isNull(instance)) {
            log.error("查找导入配置图实例失败:{}", updateImportConfigDTO.getInstanceId());
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        ModelResultVo modelResultVo = new ModelResultVo();

        LocalTransaction transaction = transactionService.createTransaction(projectId, UPDATE_MODEL);
        try {
            importConfigSetProperties(updateImportConfigDTO, instance);
            transactionService.commit(projectId);
            modelResultVo.setInstanceId(instance.getId());
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (RuntimeException e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.SERVICE_ERROR, e);
        }
        return modelResultVo;
    }

    private void importConfigSetProperties(ImportConfigDTO importConfigDTO, MetaClassInstance instance) {
        final String projectId = importConfigDTO.getProjectId();
        List<UpdateModelDTO> updateModelDtos = getMapToDataSourceProperty(importConfigDTO, instance);
        MetaClassInstance targetScopeInstance = internalUmlService.fetchInstance(importConfigDTO.getTargetScope(), projectId);
        if (Objects.nonNull(targetScopeInstance)) {
            log.info("配置图修改后目标范围为:{}", targetScopeInstance.getId());
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_ImportMap_targetScope, targetScopeInstance));
        }

        Boolean searchForElementsInTargetScopeOnly = importConfigDTO.getSearchForElementsInTargetScopeOnly();
        if (Objects.nonNull(searchForElementsInTargetScopeOnly)) {
            log.info("配置图修改后导入元素是否只搜索本身:{}", searchForElementsInTargetScopeOnly);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_ImportMap_searchForElementsInTargetScopeOnly, searchForElementsInTargetScopeOnly));
        }

        Boolean searchForReferencesInTargetScopeOnly = importConfigDTO.getSearchForReferencesInTargetScopeOnly();
        if (Objects.nonNull(searchForReferencesInTargetScopeOnly)) {
            log.info("配置图修改后引用元素是否只搜索本身:{}", searchForReferencesInTargetScopeOnly);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_ImportMap_searchForReferencesInTargetScopeOnly, searchForReferencesInTargetScopeOnly));
        }

        Boolean importInstance = importConfigDTO.getImportInstance();
        if (Objects.nonNull(importInstance)) {
            log.info("配置图修改后导入类型是否为实例:{}", importInstance);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_ImportMap_importInstance, importInstance));
        }

        MetaClassInstance elementType = internalUmlService.fetchInstance(importConfigDTO.getElementType(), projectId);
        if (Objects.nonNull(elementType)) {
            log.info("配置图修改后元素类型为:{}", elementType.getId());
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_ImportMap_elementType, elementType));
        } else {
            umlService.removeModel(projectId, instance.getId(), UMLDefinitionConstants.Design_Profile_ImportMap_elementType);
        }

        MetaClassInstance relationType = internalUmlService.fetchInstance(importConfigDTO.getRelationshipType(), projectId);
        if (Objects.nonNull(relationType)) {
            log.info("配置图修改后关系类型为:{}", relationType.getId());
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_ImportMap_elementType, relationType));
        } else {
            umlService.removeModel(projectId, instance.getId(), UMLDefinitionConstants.Design_Profile_ImportMap_elementType);
        }

        MetaClassInstance instanceClassifier = internalUmlService.fetchInstance(importConfigDTO.getInstanceClassifier(), projectId);
        if (Objects.nonNull(instanceClassifier)) {
            log.info("配置图修改后实例分类器为:{}", instanceClassifier.getId());
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_ImportMap_instanceClassifier, instanceClassifier));
        } else {
            umlService.removeModel(projectId, instance.getId(), UMLDefinitionConstants.Design_Profile_ImportMap_instanceClassifier);
        }

        List<MetaClassInstance> stereotypes = internalUmlService.fetchInstanceByIds(importConfigDTO.getStereotypes(), projectId);
        if (CollectionUtils.isNotEmpty(stereotypes)) {
            log.info("配置图修改后构造型为:{}", stereotypes.stream().map(MetaClassInstance::getId).collect(Collectors.toList()));
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_ImportMap_stereotypes, stereotypes));
        } else {
            umlService.removeModel(projectId, instance.getId(), UMLDefinitionConstants.Design_Profile_ImportMap_stereotypes);
        }

        if (CollectionUtils.isNotEmpty(updateModelDtos)) {
            umlService.updateModelByBatch(updateModelDtos);
        }
    }

    public ImportConfigVo queryImportConfig(String projectId, String instanceId) {

        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(instance)) {
            log.info("查找导入配置图实例失败:{}", instanceId);
            return null;
        }
        ImportConfigVo importConfigVO = new ImportConfigVo();
        ModelPropertyInfo importConfigModel = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId,
                instance,
                Stream.of(UMLDefinitionConstants.Design_Profile_MapToDataSource_url,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_sheet,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_firstCell,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_identificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_sourceIdentificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_targetIdentificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_mappingColumns,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_firstRowRepresentsHeading,
                        UMLDefinitionConstants.Design_Profile_ImportMap_targetScope,
                        UMLDefinitionConstants.Design_Profile_ImportMap_searchForElementsInTargetScopeOnly,
                        UMLDefinitionConstants.Design_Profile_ImportMap_searchForReferencesInTargetScopeOnly,
                        UMLDefinitionConstants.Design_Profile_ImportMap_importInstance,
                        UMLDefinitionConstants.Design_Profile_ImportMap_instanceClassifier,
                        UMLDefinitionConstants.Design_Profile_ImportMap_stereotypes).collect(Collectors.toList()));
        setMapToDataSourceProperty(importConfigVO, importConfigModel);
        MetaClassInstance targetScope = importConfigModel.queryInstanceValue(UMLDefinitionConstants.Design_Profile_ImportMap_targetScope);
        if (Objects.nonNull(targetScope)) {
            importConfigVO.setTargetScope(targetScope.getId());
            log.info("导入配置图的目标范围:{}", targetScope.getId());
        }
        Boolean searchForElementsInTargetScopeOnly = importConfigModel.queryBooleanValue(UMLDefinitionConstants.Design_Profile_ImportMap_searchForElementsInTargetScopeOnly);
        if (Objects.nonNull(searchForElementsInTargetScopeOnly)) {
            importConfigVO.setSearchForElementsInTargetScopeOnly(searchForElementsInTargetScopeOnly);
            log.info("导入配置图导入元素只搜索目标范围本身:{}", searchForElementsInTargetScopeOnly);
        }
        Boolean searchForReferencesInTargetScopeOnly = importConfigModel.queryBooleanValue(UMLDefinitionConstants.Design_Profile_ImportMap_searchForReferencesInTargetScopeOnly);
        if (Objects.nonNull(searchForReferencesInTargetScopeOnly)) {
            importConfigVO.setSearchForReferencesInTargetScopeOnly(searchForReferencesInTargetScopeOnly);
            log.info("导入配置图引用元素只搜索目标范围本身:{}", searchForReferencesInTargetScopeOnly);
        }
        Boolean importInstance = importConfigModel.queryBooleanValue(UMLDefinitionConstants.Design_Profile_ImportMap_importInstance);
        if (Objects.nonNull(importInstance)) {
            importConfigVO.setImportInstance(importInstance);
            log.info("导入配置图是否导入实例:{}", importInstance);
        }
        MetaClassInstance elementType = importConfigModel.queryInstanceValue(UMLDefinitionConstants.Design_Profile_ImportMap_elementType);
        if (Objects.nonNull(elementType)) {
            log.info("元素类型为：{}", elementType.getId());
            if (RelationConstraints.RELATION_TYPES.contains(elementType.getId())) {
                importConfigVO.setRelationshipType(elementType.getId());
            } else {
                importConfigVO.setElementType(elementType.getId());
            }
        }
        MetaClassInstance instanceClassifier = importConfigModel.queryInstanceValue(UMLDefinitionConstants.Design_Profile_ImportMap_instanceClassifier);
        if (Objects.nonNull(instanceClassifier)) {
            importConfigVO.setInstanceClassifier(instanceClassifier.getId());
            log.info("导入配置图实例分类器为:{}", instanceClassifier);
        }
        List<MetaClassInstance> stereotypes = importConfigModel.queryListInstanceValue(UMLDefinitionConstants.Design_Profile_ImportMap_stereotypes);
        if (CollectionUtils.isNotEmpty(stereotypes)) {
            importConfigVO.setStereotypes(stereotypes.stream().map(MetaClassInstance::getId).collect(Collectors.toList()));
            log.info("导入配置图导入模型构造型为:{}", stereotypes);
        }
        return importConfigVO;
    }

    /**
     * desciption:创建表格导入配置：为表格新增Design_Profile_DiagramTableMapToDataSource构造型，并设置相应属性
     *
     * @param diagramImportConfigDTO
     * @return com.huawang.mdesign.model.service.vo.ModelResultVo
     * @author lx
     * @date 2023/9/25
     */
    public ModelResultVo createDiagramImportConfig(DiagramImportConfigDTO diagramImportConfigDTO) {
        final String projectId = diagramImportConfigDTO.getProjectId();
        ModelResultVo modelResultVo = new ModelResultVo();

        LocalTransaction transaction = transactionService.createTransaction(projectId, ADD_MODEL);
        try {
            Map<String, MetaClassInstance> stereotyInstances = internalUmlService.fetchInstances(
                    Stream.of(UMLDefinitionConstants.Design_Profile_DiagramTableMapToDataSource,
                            UMLDefinitionConstants.Design_Profile_MapToDataSource).collect(Collectors.toList()),
                    projectId);
            MetaClassInstance instance = internalUmlService.fetchInstance(diagramImportConfigDTO.getInstanceId(), projectId);
            if (Objects.isNull(instance)) {
                log.error("表格模型或表格配置项元模型查找失败");
                throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
            }
            // 应用构造型属性新增DiagramTableMapToData
            Set<String> appliedStereotypes = internalUmlService.queryListInstanceProperty(
                    projectId, instance, UMLDefinitionConstants.Element_appliedStereotype)
                    .stream().map(BasicRElement::getId).collect(Collectors.toSet());
            if (!appliedStereotypes.contains(UMLDefinitionConstants.Design_Profile_DiagramTableMapToDataSource)) {
                umlService.appendModel(projectId,
                        instance.getId(),
                        UMLDefinitionConstants.Element_appliedStereotype,
                        stereotyInstances.get(UMLDefinitionConstants.Design_Profile_DiagramTableMapToDataSource));
            }
            diagramImportConfigSetProperties(diagramImportConfigDTO, instance);
            transactionService.commit(projectId);
            modelResultVo.setInstanceId(instance.getId());
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.SERVICE_ERROR, e);
        }
        return modelResultVo;
    }

    public ModelResultVo updateDiagramImportConfig(DiagramImportConfigDTO diagramImportConfigDTO) {
        final String projectId = diagramImportConfigDTO.getProjectId();
        final MetaClassInstance instance = internalUmlService.fetchInstance(diagramImportConfigDTO.getInstanceId(), projectId);
        if (Objects.isNull(instance)) {
            log.info("查找表格导入配置图实例失败:{}", diagramImportConfigDTO.getInstanceId());
            return null;
        }
        ModelResultVo modelResultVo = new ModelResultVo();

        LocalTransaction transaction = transactionService.createTransaction(projectId, UPDATE_MODEL);
        try {
            diagramImportConfigSetProperties(diagramImportConfigDTO, instance);
            transactionService.commit(projectId);
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
            modelResultVo.setInstanceId(instance.getId());
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (RuntimeException e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.SERVICE_ERROR, e);
        }
        return modelResultVo;
    }

    private void diagramImportConfigSetProperties(DiagramImportConfigDTO diagramImportConfigDTO, MetaClassInstance instance) {
        final String projectId = diagramImportConfigDTO.getProjectId();
        List<UpdateModelDTO> updateModelDtos = getMapToDataSourceProperty(diagramImportConfigDTO, instance);
        String deleteRowOption = diagramImportConfigDTO.getDeleteRowOption();
        if (Objects.nonNull(deleteRowOption)) {
            log.info("表格配置图修改后删除操作为:{}", deleteRowOption);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_DiagramTableMapToDataSource_deleteRowOption, deleteRowOption));
        }
        if (!updateModelDtos.isEmpty()) {
            umlService.updateModelByBatch(updateModelDtos);
        }
    }

    public DiagramImportConfigVo queryDiagramImportConfig(String projectId, String instanceId) {
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(instance)) {
            log.info("查找表格导入配置图实例失败:{}", instanceId);
            return null;
        }
        DiagramImportConfigVo diagramImportConfigVO = new DiagramImportConfigVo();
        ModelPropertyInfo importConfigModel = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId,
                instance,
                Stream.of(UMLDefinitionConstants.Design_Profile_MapToDataSource_url,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_sheet,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_firstCell,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_identificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_sourceIdentificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_targetIdentificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_mappingColumns,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_firstRowRepresentsHeading,
                        UMLDefinitionConstants.Design_Profile_DiagramTableMapToDataSource_deleteRowOption
                ).collect(Collectors.toList()));
        setMapToDataSourceProperty(diagramImportConfigVO, importConfigModel);
        String deleteRowOption = importConfigModel.queryStringValue(UMLDefinitionConstants.Design_Profile_DiagramTableMapToDataSource_deleteRowOption);
        if (Objects.nonNull(deleteRowOption)) {
            diagramImportConfigVO.setDeleteRowOption(deleteRowOption);
            log.info("表格导入配置图的删除操作:{}", deleteRowOption);
        }
        return diagramImportConfigVO;
    }

    /**
     * desciption:设置MapToDataSource类的相关属性
     *
     * @param mapToDataSource
     * @param modelPropertyInfo
     * @return void
     * @author lx
     * @date 2023/9/26
     */
    private void setMapToDataSourceProperty(MapToDataSource mapToDataSource, ModelPropertyInfo modelPropertyInfo) {

        String url = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.Design_Profile_MapToDataSource_url);
        if (Objects.nonNull(url)) {
            mapToDataSource.setFileUrl(url);
            log.info("导入配置图文件路径为:{}", url);
        }
        String sheet = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.Design_Profile_MapToDataSource_sheet);
        if (Objects.nonNull(sheet)) {
            mapToDataSource.setSheet(sheet);
            log.info("导入配置图导入sheet为:{}", sheet);
        }
        String firstCell = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.Design_Profile_MapToDataSource_firstCell);
        if (Objects.nonNull(firstCell)) {
            mapToDataSource.setFirstCell(firstCell);
            log.info("导入配置图导入首行为:{}", firstCell);
        }
        String identificationProperty = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.Design_Profile_MapToDataSource_identificationProperty);
        if (Objects.nonNull(identificationProperty)) {
            mapToDataSource.setIdentificationProperty(identificationProperty);
            log.info("导入配置图标识属性为:{}", identificationProperty);
        }

        String sourceTypeAndIdentificationProperty = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.Design_Profile_MapToDataSource_sourceIdentificationProperty);
        String targetTypeAndIdentificationProperty = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.Design_Profile_MapToDataSource_targetIdentificationProperty);
        if (Objects.nonNull(sourceTypeAndIdentificationProperty)) {
            String[] sourceList = sourceTypeAndIdentificationProperty.split(SystemConstants.MODEL_PROPERTY_SEPARATOR);
            if (Objects.equals(sourceList.length, 2)) {
                log.info("导入配置图关系来源类型为:{}", sourceList[0]);
                log.info("导入配置图关系来源标识属性为:{}", sourceList[1]);
                mapToDataSource.setSourceType(sourceList[0]);
                mapToDataSource.setSourceIdentificationProperty(sourceList[1]);
            }
        }
        if (Objects.nonNull(targetTypeAndIdentificationProperty)) {
            String[] targetList = targetTypeAndIdentificationProperty.split(SystemConstants.MODEL_PROPERTY_SEPARATOR);
            if (Objects.equals(targetList.length, 2)) {
                log.info("导入配置图关系目标类型为:{}", targetList[0]);
                log.info("导入配置图关系目标标识属性为:{}", targetList[1]);
                mapToDataSource.setTargetType(targetList[0]);
                mapToDataSource.setTargetIdentificationProperty(targetList[1]);
            }
        }
        List<String> mappingColumns = modelPropertyInfo.queryListStringValue(UMLDefinitionConstants.Design_Profile_MapToDataSource_mappingColumns);
        if (CollectionUtils.isNotEmpty(mappingColumns)) {
            sortMappingColumns(mappingColumns);
            mapToDataSource.setMappingColumns(mappingColumns);
        }
        Boolean firstRowRepresentsHeading = modelPropertyInfo.queryBooleanValue(UMLDefinitionConstants.Design_Profile_MapToDataSource_firstRowRepresentsHeading);
        if (Objects.nonNull(firstRowRepresentsHeading)) {
            mapToDataSource.setFirstRowRepresentsHeading(firstRowRepresentsHeading);
            log.info("导入配置图第一行是否为标题行:{}", firstRowRepresentsHeading);
        }

    }

    /**
     * desciption:将MapToDataSource属性转化为UpdateModelDTO模型更新指令
     *
     * @param mapToDataSource
     * @param instance
     * @return java.util.List<com.huawang.mdesign.model.service.dto.UpdateModelDTO>
     * @author lx
     * @date 2023/9/26
     */
    private List<UpdateModelDTO> getMapToDataSourceProperty(MapToDataSource mapToDataSource, MetaClassInstance instance) {
        List<UpdateModelDTO> updateModelDtos = new ArrayList<>();
        final String projectId = mapToDataSource.getProjectId();
        String url = mapToDataSource.getFileUrl();
        if (Objects.nonNull(url)) {
            log.info("表格配置图修改后文件路径为:{}", url);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_MapToDataSource_url, url));
        }
        String sheet = mapToDataSource.getSheet();
        if (Objects.nonNull(sheet)) {
            log.info("表格配置图修改后导入Sheet为:{}", sheet);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_MapToDataSource_sheet, sheet));
        }
        String firstCell = mapToDataSource.getFirstCell();
        if (Objects.nonNull(firstCell)) {
            log.info("表格配置图修改后导入首行为:{}", firstCell);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_MapToDataSource_firstCell, firstCell));
        }
        String identificationProperty = mapToDataSource.getIdentificationProperty();
        if (Objects.nonNull(identificationProperty)) {
            log.info("表格配置图修改后标识属性为:{}", identificationProperty);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_MapToDataSource_identificationProperty, identificationProperty));
        }
        String sourceIdentificationType = mapToDataSource.getSourceType();
        String sourceIdentificationProperty = mapToDataSource.getSourceIdentificationProperty();
        if (Objects.nonNull(sourceIdentificationType) && Objects.nonNull(sourceIdentificationProperty)) {
            log.info("配置图修改后关系来源标识属性为:{}", sourceIdentificationProperty);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_MapToDataSource_sourceIdentificationProperty,
                    String.join(SystemConstants.MODEL_PROPERTY_SEPARATOR, sourceIdentificationType, sourceIdentificationProperty)));
        } else {
            umlService.removeModel(projectId, instance.getId(), UMLDefinitionConstants.Design_Profile_MapToDataSource_sourceIdentificationProperty);
        }
        String targetIdentificationType = mapToDataSource.getTargetType();
        String targetIdentificationProperty = mapToDataSource.getTargetIdentificationProperty();
        if (Objects.nonNull(targetIdentificationType) && Objects.nonNull(targetIdentificationProperty)) {
            log.info("配置图修改后关系目标标识属性为:{}", targetIdentificationProperty);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_MapToDataSource_targetIdentificationProperty,
                    String.join(SystemConstants.MODEL_PROPERTY_SEPARATOR, targetIdentificationType, targetIdentificationProperty)));
        } else {
            umlService.removeModel(projectId, instance.getId(), UMLDefinitionConstants.Design_Profile_MapToDataSource_targetIdentificationProperty);
        }
        List<String> mappingColumns = mapToDataSource.getMappingColumns();
        if (CollectionUtils.isNotEmpty(mappingColumns)) {
            log.info("表格配置图修改后映射属性组为:{}", mappingColumns);
            umlService.removeModel(projectId, instance.getId(), UMLDefinitionConstants.Design_Profile_MapToDataSource_mappingColumns);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_MapToDataSource_mappingColumns, mappingColumns));
        }
        Boolean firstRowRepresentsHeading = mapToDataSource.getFirstRowRepresentsHeading();
        if (Objects.nonNull(firstRowRepresentsHeading)) {
            log.info("表格配置图修改后首行是否为标题行:{}", firstRowRepresentsHeading);
            updateModelDtos.add(UpdateModelFactory.newInstance(projectId, instance.getId(),
                    UMLDefinitionConstants.Design_Profile_MapToDataSource_firstRowRepresentsHeading, firstRowRepresentsHeading));
        }
        return updateModelDtos;
    }


    /**
     * desciption:对查询出的无序mappingColumns排序(根据分隔符前的A、B、C...)
     */
    private void sortMappingColumns(List<String> mappingColumns) {
        Comparator<String> columnComparator = (column1, column2) -> {
            String[] mappingColumn1 = column1.split(SystemConstants.MAPPING_COLUMNS_SEPARATOR);
            String[] mappingColumn2 = column2.split(SystemConstants.MAPPING_COLUMNS_SEPARATOR);
            if (mappingColumn1.length < 1 || mappingColumn2.length < 1) {
                log.error("mappingColumns映射列不包含分隔符__");
                throw AbortExecutionException.build(ErrorCode.QUERY_MODEL_ERROR);
            }
            String title1 = mappingColumn1[0];
            String title2 = mappingColumn2[0];
            // String自带compareTo方法会将长的排在前面
            return Objects.equals(title1.length(), title2.length()) ?
                    title1.compareTo(title2) : title1.length() - title2.length();
        };
        mappingColumns.sort(columnComparator);
        log.info("排序后的导入配置图映射关系为:{}", mappingColumns);
    }

    /**
     * desciption:表格信息写入文件
     *
     * @param projectId
     * @param instanceId
     * @return void
     * @author lx
     * @date 2023/9/25
     */
    public void writeToFile(String projectId, String instanceId, String attachfileDir) {
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(instance)) {
            log.error("表格模型查找失败");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        ModelPropertyInfo diagramModel = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId,
                instance,
                Stream.of(UMLDefinitionConstants.Design_Profile_MapToDataSource_url,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_sheet,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_firstCell,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_identificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_sourceIdentificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_targetIdentificationProperty,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_mappingColumns,
                        UMLDefinitionConstants.Design_Profile_MapToDataSource_firstRowRepresentsHeading,
                        UMLDefinitionConstants.Design_Profile_DiagramTableMapToDataSource_deleteRowOption
                ).collect(Collectors.toList()));
        // 查询模型行元素
        String sheetName = diagramModel.queryStringValue(UMLDefinitionConstants.Design_Profile_MapToDataSource_sheet);
        List<String> rowList = diagramTableService.queryRowElements(projectId, instanceId);
        List<MetaClassInstance> rowInstanceList = internalUmlService.fetchInstanceByIds(rowList, projectId);
        List<DiagramTableColumnVo> diagramTableColumnVos = diagramTableService.queryColumns(instanceId, projectId);
        if (CollectionUtils.isEmpty(rowList) || CollectionUtils.isEmpty(diagramTableColumnVos)) {
            log.info("表内行或列元素为空，无需写入内容");
            return;
        }
        String url = getRealUrl(projectId, diagramModel, attachfileDir);
        List<SheetData> sheetDataList = importPreview(url);
        List<SheetData> importSheetDataList = sheetDataList.stream().filter(it ->
                Objects.equals(sheetName, it.getSheetName())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(importSheetDataList)) {
            log.info("文件无匹配的sheet");
            return;
        }
        SheetData importSheetData = importSheetDataList.get(0);

        List<String> mappingColumns = diagramModel.queryListStringValue(UMLDefinitionConstants.Design_Profile_MapToDataSource_mappingColumns);
        if (CollectionUtils.isEmpty(mappingColumns)) {
            log.error("无映射属性列");
            throw AbortExecutionException.build(ErrorCode.PROPERTY_QUERY_ERROR);
        }
        sortMappingColumns(mappingColumns);
        List<ColumnInfo> columnInfoList = initColumnInfoList(projectId, mappingColumns);
        List<String> columns = importSheetData.getColumns();
        List<String> keys = columnInfoList.stream().map(ColumnInfo::getKey).filter(Objects::nonNull).collect(Collectors.toList());

        Boolean isInstanceDiagram = internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.TableAndMatrix_InstanceTable);
        keys.addAll(Stream.of(UMLDefinitionConstants.InstanceSpecification_slot, UMLDefinitionConstants.InstanceSpecification_classifier).collect(Collectors.toList()));
        Map<String, ModelPropertyInfo> rowInstanceMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, rowInstanceList, keys);

        Map<String, ModelPropertyInfo> slotMap = new HashMap<>();
        Map<String, ModelPropertyInfo> slotValueMap = new HashMap<>();
        if (BooleanUtils.isTrue(isInstanceDiagram)) {
            List<MetaClassInstance> slotList = rowInstanceMap.values().stream().flatMap(it ->
                    it.queryListInstanceValue(UMLDefinitionConstants.InstanceSpecification_slot).stream())
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            slotMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId,
                    slotList,
                    Stream.of(UMLDefinitionConstants.Slot_value).collect(Collectors.toList()));
            Set<String> slotValuePropertySet = slotMap.values().stream().map(it -> {
                MetaClassInstance slotValue = it.queryInstanceValue(UMLDefinitionConstants.Slot_value);
                if (Objects.isNull(slotValue)) {
                    return null;
                }
                String slotType = slotValue.getClassifier().getId();
                if (Objects.equals(slotType, UMLDefinitionConstants.InstanceValue)) {
                    return slotType + "-instance";
                } else {
                    return slotType + "-value";
                }
            }).filter(Objects::nonNull).collect(Collectors.toSet());
            List<MetaClassInstance> slotValueList = slotMap.values().stream().flatMap(it ->
                    it.queryListInstanceValue(UMLDefinitionConstants.Slot_value).stream()).filter(Objects::nonNull).collect(Collectors.toList());
            slotValueMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId,
                    slotValueList,
                    new ArrayList<>(slotValuePropertySet));
        }
        List<List<String>> contentList = new ArrayList<>(rowInstanceList.size());
        for (int row = 0; row < rowInstanceList.size(); row++) {
            MetaClassInstance rowInstance = rowInstanceList.get(row);
            // 关系来源
            RelationshipVo relationshipVo = internalUmlService.checkInstanceType(projectId, rowInstance, UMLDefinitionConstants.Relationship) ?
                    relationshipService.queryEnds(projectId, rowInstance.getId()) : new RelationshipVo();
            String sourceName = relationshipVo.getSourceName();
            String targetName = relationshipVo.getTargetName();
            ModelPropertyInfo rowInstanceInfo = rowInstanceMap.get(rowInstance.getId());
            List<String> content = getContent(projectId, new ImportColumnsInfo(columnInfoList, columns, keys, slotMap, slotValueMap, sourceName, targetName), rowInstanceInfo);
            contentList.add(content);
        }
        // 导出
        exportExcelFile(sheetName, url, sheetDataList, contentList);
    }

    private void exportExcelFile(String sheetName, String url, List<SheetData> sheetDataList, List<List<String>> contentList) {
        File excelFile = new File(url);
        if (!excelFile.exists()) {
            throw AbortExecutionException.build(ErrorCode.MODEL_FILE_NOT_FOUND);
        }
        try {
            ExcelWriter excelWriter = EasyExcelFactory.write(url).build();
            sheetDataList.forEach(it -> {
                WriteSheet writeSheet = EasyExcelFactory.writerSheet(it.getSheetName()).head(it.getColumns().stream().
                        map(Collections::singletonList).collect(Collectors.toList())).build();
                if (Objects.equals(sheetName, it.getSheetName())) {
                    excelWriter.write(contentList, writeSheet);
                } else {
                    excelWriter.write(it.getValues(), writeSheet);
                }
            });
            excelWriter.finish();
        } catch (RuntimeException e) {
            log.error("导出失败", e);
            throw AbortExecutionException.build(ErrorCode.READ_FILE_ERROR, e);
        }
    }

    @Nullable
    private List<String> getContent(String projectId,
                                    ImportColumnsInfo importColumnsInfo, ModelPropertyInfo rowInstanceInfo) {
        List<String> content = new ArrayList<>(importColumnsInfo.getColumns().size());
        for (int column = 0; column < importColumnsInfo.getColumns().size(); column++) {
            if (column >= importColumnsInfo.getColumnInfoList().size()) {
                log.error("映射列长度异常");
                throw AbortExecutionException.build(ErrorCode.COLUMN_NUMBER_ERROR);
            }

            ColumnInfo columnInfo = importColumnsInfo.getColumnInfoList().get(column);
            // 如果是关系模型两端属性：直接取名称
            if (Objects.equals(columnInfo.getPropertyType(), 1)) {
                String name = BooleanUtils.isTrue(columnInfo.getIsSource()) ? importColumnsInfo.getSourceName() : importColumnsInfo.getTargetName();
                content.add(name);
                continue;
            }

            Object propertyData = Objects.equals(columnInfo.getPropertyType(), 0) ?
                    getPropertyValue(importColumnsInfo.getKeys(), rowInstanceInfo, columnInfo) :
                    getInstanceSpecificationSlotValue(importColumnsInfo.getKeys(), rowInstanceInfo, columnInfo, importColumnsInfo.getSlotMap(), importColumnsInfo.getSlotValueMap());
            if (propertyData == null) {
                content.add("");
                continue;
            }
            // 统一转化为list进行处理
            if (BooleanUtils.isFalse(propertyData instanceof ArrayList)) {
                propertyData = Collections.singletonList(propertyData);
            }
            List<String> dataList = ((List<?>) propertyData).stream().map(it -> {
                if (it instanceof MetaClassInstance) {
                    MetaClassInstance instanceProeperty = (MetaClassInstance) it;
                    return internalUmlService.queryStringProperty(projectId, instanceProeperty, UMLDefinitionConstants.NamedElement_name);
                } else if (it instanceof String) {
                    return (String) it;
                } else {
                    return String.valueOf(it);
                }
            }).collect(Collectors.toList());
            String fileData = String.join(EXPORT_LF, dataList);
            content.add(fileData);
        }
        return content;
    }

    private String getRealUrl(String projectId, ModelPropertyInfo diagramModel, String attachFileDir) {
        String url = diagramModel.queryStringValue(UMLDefinitionConstants.Design_Profile_MapToDataSource_url);
        if (Objects.isNull(url)) {
            log.error("文件路径查找失败");
            throw AbortExecutionException.build(ErrorCode.FILE_URL_NOT_EXIST);
        }
        // 如果url为附件id:查询附件名称并拼接真实url
        MetaClassInstance attachFile = internalUmlService.fetchInstance(url, projectId);
        if (Objects.nonNull(attachFile)) {
            String attachFileName = internalUmlService.queryStringProperty(
                    projectId, attachFile, UMLDefinitionConstants.Customization_AttachedFile_file);
            AttachFile stu = new Gson().fromJson(attachFileName, AttachFile.class);
            url = attachFileDir + File.separator + stu.getFilePath();
        }
        return url;
    }

    @Nullable
    private Object getPropertyValue(List<String> keys, ModelPropertyInfo rowInstanceInfo, ColumnInfo columnInfo) {
        String key = columnInfo.getKey();
        if (!keys.contains(key)) {
            return null;
        }
        return rowInstanceInfo.queryProperty(key);
    }

    @Nullable
    private Object getInstanceSpecificationSlotValue(List<String> keys,
                                                     ModelPropertyInfo rowInstanceInfo,
                                                     ColumnInfo columnInfo,
                                                     Map<String, ModelPropertyInfo> slotMap,
                                                     Map<String, ModelPropertyInfo> slotValueMap) {
        List<MetaClassInstance> slotList = rowInstanceInfo.queryListInstanceValue(UMLDefinitionConstants.InstanceSpecification_slot);
        if (CollectionUtils.isEmpty(slotList)) {
            log.info("实例规格无插槽值");
            return null;
        }
        MetaClassInstance classifierProperty = columnInfo.getClassifierProperty();
        MetaClassInstance slot = slotList.stream().filter(it -> {
            ModelPropertyInfo modelPropertyInfo = slotMap.get(it.getId());
            return Objects.equals(modelPropertyInfo.queryInstanceValue(UMLDefinitionConstants.Slot_definingFeature), classifierProperty);
        }).findFirst().orElse(null);
        if (Objects.isNull(slot)) {
            log.info("实例规格存在插槽，但无与分类器属性匹配的插槽");
            return null;
        }
        ModelPropertyInfo slotoModelPropertyInfo = slotMap.get(slot.getId());
        List<MetaClassInstance> slotvalue = slotoModelPropertyInfo.queryListInstanceValue(UMLDefinitionConstants.Slot_value);
        if (CollectionUtils.isEmpty(slotvalue)) {
            log.info("存在与分类器属性匹配的插槽，但不存在插槽值");
            return null;
        }
        return slotvalue.stream().map(it -> {
            String slotValueType = it.getType().getId();
            String slotValueProperty = Objects.equals(slotValueType, UMLDefinitionConstants.InstanceValue) ?
                    slotValueType + "-instance" : slotValueType + "-value";
            ModelPropertyInfo slotValueModelPropertyInfo = slotValueMap.get(it.getId());
            return slotValueModelPropertyInfo.queryProperty(slotValueProperty);
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    /**
     * desciption:取消文件绑定：移除fileUrl属性
     *
     * @param importElementDTO
     * @return com.huawang.mdesign.model.service.vo.ModelResultVo
     * @author lx
     * @date 2023/9/25
     */
    public ModelResultVo unBindFileUrl(ImportElementDTO importElementDTO) {
        final String projectId = importElementDTO.getProjectId();
        final String instanceId = importElementDTO.getInstanceId();
        ModelResultVo modelResultVo = new ModelResultVo();

        LocalTransaction transaction = transactionService.createTransaction(projectId, DELETE_MODEL);
        try {
            MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
            if (Objects.isNull(instance)) {
                log.error("表格模型查找失败");
                throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
            }
            umlService.removeModel(projectId, instance.getId(), UMLDefinitionConstants.Design_Profile_MapToDataSource_url);
            transactionService.commit(projectId);
            modelResultVo.setInstanceId(instance.getId());
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.SERVICE_ERROR, e);
        }
        return modelResultVo;
    }



    public String failContentExportExcel(FailContentExportExcelDTO dto) {
        final String url = dto.getUrl();
        final List<List<String>> failContent = dto.getFailContent();
        final List<String> column = dto.getColumn();
        final List<List<String>> head = CollectionUtils.isEmpty(column) ? Collections.emptyList() :
                column.stream().map(Collections::singletonList).collect(Collectors.toList());
        Collections.reverse(failContent);
        File file = new File(url);
        try {
            ImportAndExportUtils.toExcel(head, (List) failContent, file, "导入失败信息");
        } catch (FileNotFoundException e) {
            log.error("导出失败", e);
            throw AbortExecutionException.build(ErrorCode.READ_FILE_ERROR, e);
        }
        return url;
    }

}
